<template>
  <div class="map">
    <div class="main">
      <div class="operations">
        <div>
          <div class="f-item">
            <label for="map-width">地图宽度</label
            ><input type="number" id="map-width" v-model="width" />
          </div>
          <div class="f-item">
            <label for="map-height">地图高度</label
            ><input type="number" id="map-height" v-model="height" />
          </div>
          <div class="land-list">地形边界：</div>
          <div class="ter-list f-item">
            <div class="current-grid" v-if="borderItems.length">
              <img
                :src="currentBorder.src"
                :title="currentBorder.name"
                @click="isBorderListShow = !isBorderListShow"
              />
            </div>
            <div class="grid-options" v-show="isBorderListShow">
              <div
                class="grid-item"
                v-for="item in borderItems"
                :key="item.id"
                @click="changeBorder(item)"
              >
                <img :src="item.src" :title="item.name" />
              </div>
            </div>
          </div>
          <div class="land-list">初始地形：</div>
          <div class="ter-list f-item">
            <div class="current-grid" v-if="landItems.length">
              <img
                :src="currentLand.src"
                :title="currentLand.name"
                @click="isGridListShow = !isGridListShow"
              />
            </div>
            <div class="grid-options" v-show="isGridListShow">
              <div
                class="grid-item"
                v-for="item in landItems"
                :key="item.id"
                @click="changeLand(item)"
              >
                <img :src="item.src" :title="item.name" />
              </div>
            </div>
          </div>
          <div class="f-item">
            <button id="generate" @click="createMap">创建</button>
          </div>
          <div class="f-item">
            <label for="level-name">地图名称</label
            ><input
              style="width: 120px"
              id="level-name"
              type="text"
              v-model="mapName"
            />
          </div>
          <div class="f-item">
            <button @click="saveMapHandler">保存</button>
          </div>
        </div>
      </div>
      <div class="show">
        <div class="map-grids">
          <div class="list">
            <div
              class="grid-item"
              :class="{ active: index === currentIndex }"
              v-for="(item, index) in gridItems"
              :key="index"
              @click="setCurrentIndex(index)"
            >
              <img :src="item.src" :title="item.name" />
            </div>
          </div>
          <div class="info" v-if="gridItems[currentIndex]">
            <div>名称：{{ gridItems[currentIndex].name }}</div>
            <div>空：{{ gridItems[currentIndex].air }}</div>
            <div>陆：{{ gridItems[currentIndex].land }}</div>
            <div>海：{{ gridItems[currentIndex].ocean }}</div>
          </div>
        </div>
        <div class="draw-rect">
          <div class="slider-rect">
            <canvas
              id="draw-map"
              ref="canvas"
              @mousedown="clickToPaint"
              @mouseup="painting = false"
              @mousemove="paintGrid"
            ></canvas>
          </div>
        </div>
        <div class="unit-editor"></div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
import axios from "../../common/axios";
import Tile from "../../common/model/Tile";

const gridSize = 32;

@Component({})
export default class Map extends Vue {
  private width = 30;
  private height = 20;
  private gridItems: Array<Tile> = new Array<Tile>();
  private currentIndex = 0;
  private landItems: Array<Tile> = new Array<Tile>();
  private currentLand: Tile = {} as Tile;
  private currentBorder: Tile = {} as Tile;
  private borderItems: Array<Tile> = new Array<Tile>();
  private isGridListShow = false;
  private isBorderListShow = false;
  private mapGrids: Array<Array<HTMLImageElement>> = new Array<
    Array<HTMLImageElement>
  >();
  private hasDrawMap = false;
  private painting = false;
  private canvas = {} as HTMLCanvasElement;
  private context = {} as CanvasRenderingContext2D;
  private mapName = "";
  private mapId = "";
  private enemyBots = [];
  private playerBots = [];

  created() {
    this.getMapDatas();
  }
  mounted() {
    this.canvas = this.$refs.canvas as HTMLCanvasElement;
    this.context = this.canvas.getContext("2d") as CanvasRenderingContext2D;
    this.drawAllGrid();
  }
  setCurrentIndex(index: number) {
    this.currentIndex = index;
  }
  async getMapDatas() {
    const result = await axios.get("/api/map/getAllMapTile");
    this.gridItems = result.data;
    this.landItems = result.data.filter(
      (e: Tile) =>
        e.name.includes("平地") ||
        e.name.includes("海") ||
        e.name.includes("沙") ||
        e.name.includes("地板")
    );
    this.currentLand = this.landItems[0];
    this.borderItems = result.data.filter((e: Tile) => e.name.includes("墙"));
    this.currentBorder = this.borderItems[0];

    //   this.autoLoad()
  }
  generateMapId() {
    const now = new Date();
    let year = now.getFullYear();
    let month: number | string = now.getMonth() + 1;
    month = month < 10 ? "0" + month : month;
    let day: number | string = now.getDate();
    day = day < 10 ? "0" + day : day;
    let hour: number | string = now.getHours();
    hour = hour < 10 ? "0" + hour : hour;
    let minute: number | string = now.getMinutes();
    minute = minute < 10 ? "0" + minute : minute;
    let second: number | string = now.getSeconds();
    second = second < 10 ? "0" + second : second;
    let random = Math.floor(Math.random() * 9000 + 1000);
    return `${year}-${month}-${day}-${hour}-${minute}-${second}-${random}`;
  }
  createMap() {
    if (this.hasDrawMap) {
      if (!confirm("已经存在地图数据了，你确定要重新生成吗？"))
        return alert("取消重新生成");
    }
    this.mapId = this.generateMapId();
    this.hasDrawMap = true;
    const row = this.width - 1;
    const col = this.height - 1;
    if (row < 4 || col < 4) {
      return alert("地图宽高要大点");
    }
    for (let i = 0; i <= row; i++) {
      this.mapGrids[i] = new Array<HTMLImageElement>();
      for (let j = 0; j <= col; j++) {
        const img = new Image();
        this.mapGrids[i][j] = img;
        if (i == 0 || i == row || j == 0 || j == col) {
          img.src = this.currentBorder.src;
          img.setAttribute("id", this.currentBorder.id.toString());
        } else {
          img.src = this.currentLand.src;
          img.setAttribute("id", this.currentBorder.id.toString());
        }
      }
    }
    this.drawMap();
  }
  drawMap() {
    const width = this.width * gridSize;
    const height = this.height * gridSize;
    const canvas: HTMLCanvasElement = this.$refs.canvas as HTMLCanvasElement;
    canvas.width = width;
    canvas.height = height;
    this.drawAllGrid();
  }
  drawAllGrid() {
    this.mapGrids.forEach((arr, x) => {
      arr.forEach((img, y) => {
        this.context.drawImage(
          img,
          x * gridSize,
          y * gridSize,
          gridSize,
          gridSize
        );
      });
    });
  }
  changeBorder(item: Tile) {
    this.currentBorder = item;
    this.isBorderListShow = !this.isBorderListShow;
  }
  changeLand(item: Tile) {
    this.currentLand = item;
    this.isGridListShow = !this.isGridListShow;
  }
  clickToPaint(e: MouseEvent) {
    this.painting = true;
    this.paintGrid(e);
  }
  paintGrid(e: MouseEvent) {
    if (!this.painting || !this.hasDrawMap) return;
    const mx = e.offsetX;
    const my = e.offsetY;
    const x = Math.floor(mx / gridSize);
    const y = Math.floor(my / gridSize);
    const img = new Image();
    img.src = this.gridItems[this.currentIndex].src;
    // img.id = this.gridItems[this.currentIndex].id;
    img.setAttribute("id", this.gridItems[this.currentIndex].id.toString());
    this.mapGrids[x][y] = img;
    this.context.drawImage(img, x * gridSize, y * gridSize, gridSize, gridSize);
  }
  async saveMapHandler() {
    const mapIds = this.mapGrids.map((array) => {
      return array.map((tile) => parseInt(tile.id));
    });
    console.log(this.mapId);
    console.log(mapIds);
    const result = await axios.post("/saveLevelMap", {
      mapId: this.mapId,
      mapIds,
      mapName: this.mapName,
      enemyBots: this.enemyBots,
      playerBots: this.playerBots,
    });
    console.log(result);
  }
}
</script>
<style lang="less">
.map {
  width: 100%;
}
.main {
  width: 100%;
  // height: 100vh;
  padding: 10px;
}
.show {
  display: flex;
}
.map-grids {
  width: 190px;
}
.list {
  padding: 4px;
  display: flex;
  flex-wrap: wrap;
  box-shadow: 0 0 4px 2px #ccc;
  margin-bottom: 10px;
  /* justify-content: space-between; */
}
.info {
  padding: 10px;
  box-shadow: 0 0 4px 2px #ccc;
}
.grid-item {
  margin: 2px 4px 0 0;
}
.grid-item.active {
  box-shadow: 0 2px 4px 2px rgb(251, 10, 91);
  animation: hover 1000ms infinite;
  animation-direction: alternate-reverse;
}
@keyframes hover {
  0% {
    transform: translateY(0%);
  }
  100% {
    transform: translateY(-10%);
  }
}
.draw-rect {
  flex: 1;
  margin: 0 10px;
  box-shadow: 0 0 4px 2px #ccc;
  overflow: auto;
  max-height: 700px;
}
.unit-editor {
  width: 240px;
  box-shadow: 0 0 4px 2px #ccc;
}
.operations {
  box-shadow: 0 0 4px 2px #ccc;
  padding: 10px;
  margin-bottom: 10px;
  font-size: 16px;
}
.operations > div {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.operations input {
  width: 40px;
  height: 30px;
  border: 1px solid #00e;
  outline: 0 none;
  border-radius: 4px;
  margin: 0 8px;
}
.operations button {
  width: 80px;
  height: 30px;
  background-color: #09f;
  border: 0 none;
  border-radius: 4px;
  color: #fff;
}
.operations button:active {
  background-color: rgb(4, 120, 197);
}
.f-item {
  padding-right: 10px;
}
.ter-list {
  position: relative;
}
.grid-options {
  position: absolute;
  left: -70px;
  padding: 4px;
  display: flex;
  flex-wrap: wrap;
  width: 152px;
  box-shadow: 0 0 4px 2px #ccc;
}
</style>
